﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SlopeViewer
{
    partial class EditForm : Form
    {
        struct AnchroPoint
        {
            public int Index { get; set; }
            public float Pitch { get; set; }
            public float Roll { get; set; }

            public override string ToString()
            {
                return String.Format("[{0:0000000}] : Pitch = {1:#0.0#}, Roll = {2:#0.0#}", 
                    Index, Pitch, Roll);
            }
        }

        public delegate void ApplyChangeHandler(List<SamplePoint> samples);
        public ApplyChangeHandler OnApplyChange { get; set; }
        private List<SamplePoint> _samples;

        public EditForm(List<SamplePoint> samples)
        {
            InitializeComponent();
            _samples = samples;

            // Add First & Last item
            //_anchorPoints = new List<AnchroPoint>();
            list_Samples.Items.Clear();
            list_Samples.Items.Add(
                new AnchroPoint() 
                {
                    Index = 0,
                    Pitch = _samples[0].Pitch,
                    Roll = _samples[0].Roll
                });
            list_Samples.Items.Add(
                new AnchroPoint()
                {
                    Index = _samples.Count - 1,
                    Pitch = _samples[_samples.Count - 1].Pitch,
                    Roll = _samples[_samples.Count - 1].Roll
                });

            list_Samples.SelectedIndex = 0;
        }

        private void LinearConstruction()
        {
            // There always are at least two anchor points!!
            int currentIndex = 1;
            AnchroPoint prev = (AnchroPoint)list_Samples.Items[0];
            AnchroPoint next = (AnchroPoint)list_Samples.Items[1];

            while (true)
            {
                // Interpolate
                for (int i = prev.Index; i < next.Index; ++i)
                {
                    float ratio = (float)(i - prev.Index) / (next.Index - prev.Index);

                    _samples[i].Pitch = prev.Pitch * (1.0f - ratio) + next.Pitch * ratio;
                    _samples[i].Roll = prev.Roll * (1.0f - ratio) + next.Roll * ratio;
                }

                if (currentIndex == list_Samples.Items.Count - 1)
                {
                    // Modify last sample
                    _samples[next.Index].Pitch = next.Pitch;
                    _samples[next.Index].Roll = next.Roll;
                    break;
                }

                prev = next;
                next = (AnchroPoint)list_Samples.Items[++currentIndex];
            }
        }

        private void QuadricConstruction()
        {
            /*
            // There always are at least two anchor points!!
            int currentIndex = 1;
            AnchroPoint p0 = (AnchroPoint)list_Samples.Items[0];
            AnchroPoint p1 = (AnchroPoint)list_Samples.Items[1];
            AnchroPoint p2 = (AnchroPoint)list_Samples.Items[2];

            while (true)
            {
                // Interpolate
                for (int i = prev.Index; i < next.Index; ++i)
                {
                    float ratio = (float)(i - prev.Index) / (next.Index - prev.Index);

                    _samples[i].Pitch = prev.Pitch * (1.0f - ratio) + next.Pitch * ratio;
                    _samples[i].Roll = prev.Roll * (1.0f - ratio) + next.Roll * ratio;
                }

                if (currentIndex == list_Samples.Items.Count - 1)
                {
                    // Modify last sample
                    _samples[next.Index].Pitch = next.Pitch;
                    _samples[next.Index].Roll = next.Roll;
                    break;
                }

                prev = next;
                next = (AnchroPoint)list_Samples.Items[++currentIndex];
            }
             * */
        }

        private void btn_Apply_Click(object sender, EventArgs e)
        {
            LinearConstruction();
            OnApplyChange(_samples);
        }

        private void list_Samples_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (list_Samples.SelectedItem != null)
            {
                AnchroPoint p = (AnchroPoint)list_Samples.SelectedItem;
                txt_Index.Text = "" + p.Index;
                txt_Pitch.Text = "" + p.Pitch;
                txt_Roll.Text = "" + p.Roll;

                btn_Modify.Enabled = true;

                // Cannot remove first and last item!!
                if (p.Index == 0 || p.Index == _samples.Count - 1)
                {
                    btn_Remove.Enabled = false;
                }
                else
                {
                    btn_Remove.Enabled = true;
                }
            }
            else
            {
                txt_Index.Text = "";
                txt_Pitch.Text = "";
                txt_Roll.Text = "";

                btn_Modify.Enabled = false;
                btn_Remove.Enabled = false;
            }
        }

        private void btn_Modify_Click(object sender, EventArgs e)
        {
            AnchroPoint p = (AnchroPoint)list_Samples.SelectedItem;
            p.Index = Int32.Parse(txt_Index.Text);
            p.Pitch = float.Parse(txt_Pitch.Text);
            p.Roll = float.Parse(txt_Roll.Text);
            list_Samples.Items[list_Samples.SelectedIndex] = p;
        }

        private void btn_Add_Click(object sender, EventArgs e)
        {
            AnchroPoint newP = new AnchroPoint();
            newP.Index = Int32.Parse(txt_Index.Text);
            newP.Pitch = float.Parse(txt_Pitch.Text);
            newP.Roll = float.Parse(txt_Roll.Text);

            // Check duplicate
            int insertIndex = 0;
            foreach (AnchroPoint p in list_Samples.Items)
            {
                if (p.Index == newP.Index)
                {
                    return;
                }

                if (p.Index > newP.Index) break;
  
                ++insertIndex;
            }

            list_Samples.Items.Insert(insertIndex, newP);
        }

        private void btn_Remove_Click(object sender, EventArgs e)
        {
            list_Samples.Items.RemoveAt(list_Samples.SelectedIndex);
        }
    }
}
